package cn.xeblog.plugin.game.sudoku.algorithm;

import java.util.Random;

/**
 * 随机的数独{@link Grid}生成器
 * <p>
 * <a href="https://github.com/a11n/sudoku">来源</a>
 * <p>
 */
public class Generator {

    private Solver solver;

    /**
     * 构造一个生成实例.
     */
    public Generator() {
        this.solver = new Solver();
    }

    /**
     * 使用给定数量的空{@link Grid.Cell}生成一个随机{@link Grid}实例。
     * <br><br>
     * 注意:人类玩家的复杂性会随着空{@link Grid.Cell}数量的增加而增加。
     *
     * @param numberOfEmptyCells 空{@link Grid.Cell}的数量
     * @return 一个随机填充的数独{@link Grid}与给定数量的空 {@link Grid.Cell}
     */
    public Grid generate(int numberOfEmptyCells) {
        Grid grid = generate();
        this.eraseCells(grid, numberOfEmptyCells);
        return grid;
    }

    /**
     * 消除单元格
     *
     * @param grid               网格对象
     * @param numberOfEmptyCells 空单元格的数量
     */
    private void eraseCells(Grid grid, int numberOfEmptyCells) {

        Random random = new Random();

        int i = 0;
        // 只要少于空单元格的数量，则将网格中的随机单元格置空
        while (i < numberOfEmptyCells) {
            // 随机单元格
            int randomRow = random.nextInt(9);
            int randomColumn = random.nextInt(9);
            Grid.Cell cell = grid.getCell(randomRow, randomColumn);

            if (!cell.isEmpty()) {
                // 置空
                cell.setValue(0);
            } else {
                // 如果已经为空，将+1减回来
                i--;
            }
            // 累加计数
            i++;
        }
    }

    /**
     * 生成网格
     *
     * @return 网格
     */
    private Grid generate() {
        // 空的网格
        Grid grid = Grid.emptyGrid();
        // 解算
        solver.solve(grid);
        return grid;
    }
}
